home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
amok_lha
/
amok58.lha
/
NPrint
/
txt
/
Print.mod
< prev
next >
Wrap
Text File
|
1993-08-15
|
18KB
|
747 lines
(**********************************************************************
:Program. Print
:Contents. Formation of german text
:Author. Oliver Schersand
:Address. Schillerstr 4 7805 Bötzingen
:Phone. 07663/3049
:Copyright. Public Domain
:Language. Modula-2
:Translator. M2Amiga AMSoft 3.3d
:History. V1.0 11.02.1991
**********************************************************************)
(* $V- $R- $S- $F- *)
MODULE Print;
FROM FileSystem IMPORT Lookup,Close,ReadChar,File,Response,WriteChar,
WriteBytes;
FROM Conversions IMPORT ValToStr,StrToVal;
FROM InOut IMPORT Read,Write,WriteInt,WriteString,WriteLn,
ReadString;
IMPORT InOut;
FROM Str IMPORT FirstPos,Concat,Compare,Length,Copy;
FROM Arts IMPORT Assert,Terminate,BreakPoint,TermProcedure;
FROM SYSTEM IMPORT ADR,ADDRESS;
FROM Arguments IMPORT GetArg,NumArgs;
FROM Trenne IMPORT Trennstrich;
FROM StringForm IMPORT CutBlanks,Indent;
FROM StringOps IMPORT InsertChar,FindChar,DeleteSubString;
FROM ARP IMPORT GetEnv,SetEnv;
IMPORT ASCII;
TYPE Entscheidung = (ja,nein);
Ausgabe = (rechtsb,linksb,block,zentriert);
Commands = (reset, (* Drucker resetten *)
italicsOn, (* Kursiv ein *)
underlineOn, (* Unterstreichen ein *)
boldOn, (* fettdruck ein *)
plain, (* Normalschrift *)
lq1,
draft,
elite, (* Zeichenbreite elite 12 CPI *)
pica, (* 10 CPI *)
small, (* 15 CPI *)
propOn, (* proportionalschrift ein *)
propOff,
schatten, (* Schattenschrift ein *)
suOff, (* Schatten und oder Umriss aus *)
lrMargin, (* Linker und Rechter Rand festlegen *)
lowSpace, (* 1/8 Zoll Zeilenabstand *)
normSpace (* 1/6 Zoll Zeilenabstand *)
);
Parameter = RECORD (* Druckeinstellungen *)
rmarg,lmarg : CARDINAL;
pageoffset : CARDINAL;
pagelen : CARDINAL;
darst : Ausgabe;
trenne : BOOLEAN;
pagenumber : BOOLEAN;
END;
String = ARRAY[0..200] OF CHAR;
VAR Lese,Drucker : File; (* Externe Dateien *)
ch : CHAR; (* Letztes gelesende Zeichen *)
getBuffer : ARRAY[0..255] OF CHAR; (* Puffer für Variabeln *)
getCount : [0..255]; (* Position in Puffer *)
art,
Wort, (* aktuell gescanntes Wort *)
Datei : String; (* aktuelle Eingabedatei (Toplevel) *)
dir : BOOLEAN;
Format : Parameter;
Rest : String; (* Zeilenüberhang *)
breite,Zeile : CARDINAL; (* Zeilengröße *)
Konsonanten,Vokale,Trunc : String; (* Für die Trennung *)
Seite : CARDINAL; (* Aktuelle Seite *)
(* Variabeln für die Benutzerschnittstelle *)
outx,outy : INTEGER; (* Stelle an der Trennvorschlag erscheint *)
len : INTEGER;
FilePuffer : ARRAY[1..40] OF RECORD (* Record für Dateistapel *)
f : File;
c : CHAR;
END;
FilePoint : [1..40]; (* Maximal 40 Files tief verschachtelt *)
gCom, (* Puffer für die Kommandos *)
gPuffer : ARRAY[0..400] OF CHAR; (* Puffer für die aktuellen Zeile *)
gStartupDatei : String; (* Die Startup-Datei *)
gComPos,gPos : CARDINAL; (* Position in den zwei Puffern *)
FirstLine : BOOLEAN; (* Ob in erster Zeile einer Seite *)
EndOfFile : BOOLEAN; (* Ob letzer Buchstaben gelesen *)
(*
Gibt Kommando in ein Zeichenpuffer und notiert ihre Stelle in der
Zeile
*)
PROCEDURE Com(com : Commands; a,b : INTEGER);
PROCEDURE EscAndChar ( a : ARRAY OF CHAR);
VAR i : INTEGER;
BEGIN
gCom[gComPos] := CHAR(27); INC(gComPos);
FOR i := 0 TO Length(a)-1 DO
IF a[i] # " " THEN gCom[gComPos] := a[i]; INC(gComPos); END;
END;
END EscAndChar;
VAR res : CARDINAL;
BEGIN
res := gComPos;
gCom[res+1] := CHAR(gPos); INC(gComPos,2);
CASE com OF
reset : WriteChar(Drucker,CHAR(27));WriteChar(Drucker,"c") |
italicsOn : EscAndChar("[3m") |
underlineOn : EscAndChar("[4m") |
plain : EscAndChar("[0m") |
boldOn : EscAndChar("[1m") |
lq1 : EscAndChar('[2"z') |
draft : EscAndChar('[1"z') |
elite : EscAndChar("[2w") |
pica : EscAndChar("[0w") |
small : EscAndChar("[4w") |
schatten : EscAndChar('[6"z') |
suOff : EscAndChar('[5"z') |
lowSpace : EscAndChar("[0z") |
normSpace : EscAndChar("[1z") |
END;
IF gComPos - res < 3 THEN
gComPos := res
ELSE
gCom[res] := CHAR(gComPos - (res+2));
gCom[gComPos] := 0C;
END;
END Com;
(* Ende eines Includes *)
PROCEDURE TestEndFile() : BOOLEAN;
BEGIN
IF FilePoint = 1 THEN RETURN TRUE END;
Close(FilePuffer[FilePoint].f);
DEC(FilePoint);
Lese := FilePuffer[FilePoint].f;
ch := FilePuffer[FilePoint].c;
RETURN FALSE
END TestEndFile;
(* Liest aus Variablenpuffer oder Datei ein Zeichen *)
PROCEDURE get();
VAR i : INTEGER;
BEGIN
IF getCount # 0 THEN
ch := getBuffer[0];
FOR i := 1 TO getCount DO getBuffer[i-1] := getBuffer[i] END;
DEC(getCount);
ELSE
IF Lese.eof THEN
EndOfFile := TestEndFile();
IF EndOfFile THEN ch := " " END;
ELSE
ReadChar(Lese,ch);
END;
END;
END get;
(* Liest ein Zeichen ein überliest überzählige Leerzeichen *)
PROCEDURE GetCh;
BEGIN
IF ch = " " THEN
REPEAT
get;
IF (ch < " ") THEN ch := " " END;
UNTIL (ch # " ") OR (EndOfFile);
ELSE
get;
IF ch < " " THEN ch := " " END;
END;
END GetCh;
(* Einlesen eines Wortes mit Trennzeichen am Ende des Wortes *)
PROCEDURE ScanWord;
VAR i : INTEGER;
test : CHAR;
BEGIN
i := 0;
LOOP
Wort[i] := ch; INC(i);
IF (FirstPos(Trunc,0,ch)#-1) OR EndOfFile OR (ch<" ") THEN
IF i = 1 THEN GetCh ELSE DEC(i) END;
EXIT
END;
GetCh;
END;
Wort[i] := 0C;
END ScanWord;
(* Transferiert Variabel in eine Puffer von GetChar *)
PROCEDURE GetVariable();
VAR Puffer : String;
len,i : LONGINT;
erg : POINTER TO String;
BEGIN
erg := GetEnv(ADR(Wort),ADR(Puffer),200);
i := 0;
REPEAT getBuffer[getCount] := erg^[i]; INC(i); INC(getCount) UNTIL erg^[i] = 0C;
END GetVariable;
(* Scanned Wort ein und includet wenn nötig eine Variable *)
PROCEDURE VScan();
BEGIN
ScanWord();
IF Wort[0] = "$" THEN ScanWord; GetVariable(); ScanWord(); END;
END VScan;
(* Includet eine neue Datei *)
PROCEDURE NewFile;
VAR Test : File;
BEGIN
VScan; VScan;
Lookup(Test,Wort,1024,FALSE);
IF Test.res = done THEN
FilePuffer[FilePoint].f := Lese;
FilePuffer[FilePoint].c := ch;
INC(FilePoint);
Lese := Test;
GetCh;
ELSE
WriteString("Datei:");WriteString(Wort);WriteString(" nicht gefunden!");
WriteLn;
END;
END NewFile;
PROCEDURE GetCom;
VAR add,len : LONGINT;
puff : String;
PROCEDURE GetVal(VAR l : LONGINT);
VAR err,sgn : BOOLEAN;
BEGIN
REPEAT
VScan;
UNTIL ("0" <= Wort[0]) AND (Wort[0] <= "9") OR EndOfFile;
StrToVal(Wort,l,sgn,10,err);
END GetVal;
BEGIN
ScanWord;
IF Compare(Wort,"bold")=0 THEN
Com(boldOn,0,0)
ELSIF Compare(Wort,"i")=0 THEN
NewFile;
ELSIF Compare(Wort,"draft")=0 THEN
Com(draft,0,0);
ELSIF Compare(Wort,"pica") = 0 THEN
Com(pica,0,0)
ELSIF Compare(Wort,"reset") = 0 THEN
Com(reset,0,0)
ELSIF Compare(Wort,"elite") = 0 THEN
Com(elite,0,0)
ELSIF Compare(Wort,"small") = 0 THEN
Com(small,0,0)
ELSIF Compare(Wort,"lowSpace") = 0 THEN
Com(lowSpace,0,0)
ELSIF Compare(Wort,"normSpace") = 0 THEN
Com(normSpace,0,0)
ELSIF Compare(Wort,"shadow") = 0 THEN
Com(schatten,0,0)
ELSIF Compare(Wort,"shadowOff") = 0 THEN
Com(suOff,0,0)
ELSIF Compare(Wort,"underline")=0 THEN
Com(underlineOn,0,0)
ELSIF Compare(Wort,"italics")=0 THEN
Com(italicsOn,0,0)
ELSIF Compare(Wort,"plain")=0 THEN
Com(plain,0,0);
ELSIF Compare(Wort,"lq1")=0 THEN
Com(lq1,0,0);
ELSIF Compare(Wort,"center")=0 THEN
Format.darst := zentriert
ELSIF Compare(Wort,"leftjustify")=0 THEN
Format.darst := linksb;
ELSIF Compare(Wort,"rightjustify")=0 THEN
Format.darst := rechtsb;
ELSIF Compare(Wort,"fulljustify")=0 THEN
Format.darst := block;
ELSIF Compare(Wort,"pagenumber")=0 THEN
Format.pagenumber := TRUE;
Seite := 1;
ELSIF Compare(Wort,"lrmargin")=0 THEN
GetVal(len);
GetVal(add);
Format.lmarg := len;
Format.rmarg := add;
breite := add - len;
IF breite < 10 THEN
WriteString("Grenzen falsch gewählt:");WriteInt(len,10);WriteInt(add,10);
WriteLn;
breite := 10
END;
ELSIF Compare(Wort,"pagelen")=0 THEN
GetVal(len);
Format.pagelen := len;
ELSIF Compare(Wort,"pageoffset")=0 THEN
GetVal(len);
Format.pageoffset := len;
ELSIF Compare(Wort,"trenne") = 0 THEN
Format.trenne := TRUE;
ELSIF Compare(Wort,"trenneAus") = 0 THEN
Format.trenne := FALSE;
ELSIF Compare(Wort,"newPage") = 0 THEN
Wort := "^ ";
Zeile := Format.pagelen+20;
RETURN;
ELSIF Compare(Wort,"s") = 0 THEN
VScan;
(* Variablennamen *)
VScan();
Copy(puff,Wort);
VScan;
(* Variablenwert *)
VScan();
IF Wort[0] = '"' THEN
Wort[0] := ch;
add := 1;
REPEAT GetCh; Wort[add] := ch; INC(add) UNTIL Wort[add-1] = '"';
DEC(add);Wort[add] := 0C;
GetCh;GetCh;
END;
IF NOT SetEnv(ADR(puff),ADR(Wort)) THEN
WriteString("Variable ");WriteString(puff);WriteString(" := ");
WriteString(Wort);WriteString(" nicht gesetzt.");WriteLn;
END;
ELSE
CASE Wort[0] OF
| "$" : Wort[0] := 4C;
| "\" : Wort[0] := 3C;
| "^" : Wort[0] := 1C;
| "_" : Wort[0] := 2C;
| "{" : Wort[0] := 5C;
| "}" : Wort[0] := 6C;
ELSE
WriteString("Unbekanntes Kommando:");WriteString(Wort);WriteLn;
Wort[0] := 0C;
END;
RETURN
END;
Wort[0] := 0C;
IF ch = "|" THEN GetCh END;
END GetCom;
PROCEDURE Scan;
BEGIN
ScanWord();
CASE Wort[0] OF
| "$" : ScanWord; GetVariable(); ScanWord();
| "\" : GetCom;
ELSE
END;
END Scan;
PROCEDURE SeiteAusDrucker;
BEGIN
WriteChar(Drucker,CHAR(0CH));
END SeiteAusDrucker;
PROCEDURE Startseite;
VAR i,insert : CARDINAL;
str : String;
err : BOOLEAN;
BEGIN
IF Format.pagenumber THEN
ValToStr(Seite,FALSE,str,10,5," ",err);
CutBlanks(str);
InsertChar(str,"-",0);InsertChar(str,"-",Length(str));
insert := Format.lmarg + (breite - Length(str)) DIV 2;
FOR i := 1 TO insert DO InsertChar(str," ",0) END;
FOR i := 0 TO Length(str)-1 DO
WriteChar(Drucker,str[i]);
END;
END;
FOR i := 1 TO Format.pageoffset DO WriteChar(Drucker,12C) END;
END Startseite;
PROCEDURE SendeZeile();
VAR i,j,pos,insert, len,offset : CARDINAL;
start : INTEGER;
ll : LONGINT;
BEGIN
WITH Format DO
(* Berechnet den rechten Rand der Darstellung *)
CutBlanks(gPuffer);
insert := lmarg;
len := Length(gPuffer);
CASE darst OF
| rechtsb : insert := insert + breite - len ;
| zentriert : insert := insert + (breite - len) DIV 2;
ELSE
END;
(* fügt die Commandosequencen in den String ein *)
i := 0;offset := 0;
WHILE gCom[i] # 0C DO
len := INTEGER(gCom[i]); INC(i);
pos := INTEGER(gCom[i]) + INTEGER(offset); INC(i);
INC(offset,len);
IF pos > Length(gPuffer) THEN pos := Length(gPuffer) END;
INC(i,len);
FOR j := 1 TO len DO
DEC(i);
InsertChar(gPuffer,gCom[i],pos);
END;
INC(i,len);
END;
(* Macht dann wenn nötig Blocksatz *)
IF darst = block THEN
IF len > (breite*2 DIV 3) THEN (* gibt zu große Lücken *)
start := 0;
IF FindChar(gPuffer," ",0) # -1 THEN
WHILE len < breite DO (* verteilt Lücken gleichmäßig *)
start := FindChar(gPuffer," ",start);
IF start = -1 THEN
start := FindChar(gPuffer," ",0);
END;
InsertChar(gPuffer," ",start);INC(start,2);
INC(len);
END;
END;
END;
END;
(* Sendet die Startlinie ergibt die möglichkeit in der ersten !! Zeile
kommandos wie in der Startupdatei zu plazieren
*)
IF FirstLine THEN FirstLine := FALSE; Startseite() END;
(* Fügt rand ein und sendet das dann auf die Datei *)
FOR i := 1 TO insert DO InsertChar(gPuffer," ",0) END;
IF gPuffer[0] # 0C THEN
FOR i := 0 TO Length(gPuffer)-1 DO
CASE gPuffer[i] OF
| 1C : gPuffer[i] := "^";
| 2C : gPuffer[i] := "_";
| 3C : gPuffer[i] := "\";
| 4C : gPuffer[i] := "$";
| 5C : gPuffer[i] := "{";
| 6C : gPuffer[i] := "}";
| "_" : gPuffer[i] := " ";
ELSE
END;
WriteChar(Drucker,gPuffer[i]);
END;
END;
gPos := 0;
gComPos := 0;
gPuffer[0] := 0C;
gCom[0] := 0C;
END;
END SendeZeile;
PROCEDURE Send (VAR daten : ARRAY OF CHAR);
VAR len,i : LONGINT;
BEGIN
len := Length (daten);
i := 0;
WHILE i < len DO
gPuffer[gPos] := daten[i];
INC(i); INC(gPos);
END;
gPuffer[gPos] := 0C;
daten[0] := 0C;
END Send;
PROCEDURE Trenne (VAR wort : String;
pos : CARDINAL);
VAR i : INTEGER;
buffer : String;
buf : CHAR;
BEGIN
IF (NOT Format.trenne) OR (pos < 4) THEN RETURN END;
Trennstrich(wort,"~");
DEC(pos,2);
WHILE (pos>0) & (wort[pos]#"~") & (wort[pos]#" ") DO DEC(pos) END;
IF pos > 1 THEN
wort[pos] := "-";
buf := wort[pos+1];
wort[pos+1] := 0C;
Copy(buffer,wort);
REPEAT
i := FindChar(buffer,"~",0);
IF i # -1 THEN
DeleteSubString(buffer,i,1);
END;
UNTIL i = -1;
Send(buffer);
wort[pos+1] := buf;
DeleteSubString(wort,0,pos+1);
END;
REPEAT
i := FindChar(wort,"~",0);
IF i # -1 THEN
DeleteSubString(wort,i,1);
END;
UNTIL i = -1;
END Trenne;
PROCEDURE Druckezeile(VAR rest : String);
VAR i,Laenge,len : LONGINT;
next : ARRAY[0..1] OF CHAR;
buf : CHAR;
BEGIN
next[0] := 12C; next[1] := 0C;
Wort := rest;
WHILE Wort[0] = " " DO DeleteSubString(Wort,0,1) END;
WHILE (Wort[0] = 0C) AND NOT EndOfFile DO
Scan;
WHILE Wort[0] = " " DO DeleteSubString(Wort,0,1) END;
END;
Laenge := Length(Wort);
len := Length(Wort);
LOOP
IF Wort[0] = "^" THEN DEC(Laenge,len); Wort[0] := 0C; EXIT END;
IF NOT(Laenge <= LONGINT(breite)) THEN EXIT END;
Send(Wort);
Scan;
len := Length(Wort);
INC(Laenge,len);
END;
IF len >= Laenge THEN
FOR i := breite TO Laenge+1 DO
rest[CARDINAL(i)-breite] := Wort[i];
END;
Wort[breite] := 0C;
Send(Wort);
ELSIF Laenge > LONGINT(breite) THEN
DEC(Laenge,len);
Trenne(Wort,(breite-CARDINAL(Laenge)));
rest := Wort;
ELSE rest := 0C;
END;
SendeZeile();
WriteChar(Drucker,12C);
END Druckezeile;
PROCEDURE LoadPrefs;
BEGIN
Lookup(Lese,gStartupDatei,5000,FALSE);
IF Lese.res = done THEN
WriteChar(Drucker,CHAR(27));WriteChar(Drucker,"c");
GetCh;
WHILE NOT EndOfFile DO
Scan;
END;
Close(Lese);
ELSE
WriteString("Startupdatei : ");WriteString(gStartupDatei);
WriteString(" nicht gefunden.");WriteLn;
END;
END LoadPrefs;
PROCEDURE DruckeText();
BEGIN
WriteString("Von ");WriteString(Datei);WriteString(" nach ");
WriteString(art);WriteLn;
Lookup (Drucker,art,5000,TRUE);
IF (Drucker.res = done) THEN LoadPrefs END;
Lookup (Lese,Datei,5000,FALSE);
IF (Lese.res = done) AND (Drucker.res = done) THEN
Rest[0] := 0C;
Seite := 1;
FirstLine := TRUE;
EndOfFile := FALSE;
Zeile := 1;
REPEAT
WHILE (Zeile < Format.pagelen) AND NOT EndOfFile DO
Druckezeile (Rest);
INC (Zeile);
Write(".");
END;
Write("|"); WriteLn;
SeiteAusDrucker;
INC (Seite);
Zeile := 1;
FirstLine := TRUE;
UNTIL EndOfFile;
Close (Drucker);
Close (Lese);
WriteString(" Drucken beendet.");WriteLn;
ELSE
IF Lese.res # done THEN
WriteString("Eingabedatei:");WriteString(Datei);
WriteString(" konnte nicht geöffnet werden");WriteLn;
ELSE
WriteString("Ausgabedatei:");WriteString(art);
WriteString(" konnte nicht geöffnet werden");WriteLn;
END;
END;
END DruckeText;
PROCEDURE Interactive();
BEGIN
LOOP
WriteString("Input > "); ReadString(Datei);
WriteString("Output > "); ReadString(art);
IF (Datei[0]=0C) OR (art[0]=0C) THEN EXIT END;
DruckeText();
END;
END Interactive;
(* ======================= Hauptprogramm ================================ *)
BEGIN
Konsonanten := "bcdfghklmnpqrstvwxyz";
Vokale := "aeijouüäö";
Trunc := ' |"(){}[];!?+^*#-§$%&\';
FilePoint := 1;
gPos := 0;
gComPos := 0;
gCom[0] := 0C;
getCount := 0;
WITH Format DO
pagelen := 60;
pageoffset := 0;
rmarg := 80;
lmarg := 0;
darst := linksb;
trenne := FALSE;
pagenumber := FALSE;
END;
breite := 80;
gStartupDatei := "s:Print-Startup.txt";
CASE NumArgs() OF
| 0 : Interactive()
| 1 : GetArg (1,gStartupDatei,len);Interactive()
| 2 : GetArg (1,Datei,len);
GetArg (2,art,len);
DruckeText();
| 3 : GetArg (1,gStartupDatei,len);
GetArg (2,Datei,len);
GetArg (3,art,len);
DruckeText();
ELSE
WriteString("Zuviele Argumente!");WriteLn;
WriteString("[Startupdatei] [Input Output]");WriteLn;
END;
END Print.